package cn.forge.mall.framework.web.config;

import cn.forge.mall.framework.web.core.GlobalExceptionHandler;
import cn.forge.mall.framework.web.core.util.WebFrameworkUtils;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.annotation.Resource;

/**
 * @author liangyuanping
 * @ClassName ForgeWebAutoConfiguration
 * @description:
 * @date 2024年03月21日
 * @version: 1.0
 */
@AutoConfiguration
@EnableConfigurationProperties(WebProperties.class)
public class ForgeWebAutoConfiguration implements WebMvcConfigurer {


    @Resource
    private WebProperties webProperties;

    @Bean
    public GlobalExceptionHandler globalExceptionHandler(){
        return new GlobalExceptionHandler();
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurePathMatch(configurer, webProperties.getAdminApi());
        configurePathMatch(configurer, webProperties.getAppApi());
    }

    /**
     * 设置 API 前缀，仅仅匹配 controller 包下的
     *
     * 这种设置的目的可能是为了对不同的 API 进行路径前缀的统一管理，并且将这些 API 与特定的 controller 包进行关联。通过这种方式，可以更好地组织和管理 API，使代码更具可读性和可维护性。
     *
     * 各业务服务端实际接口(不包含API前缀的)：http://172.16.135.39:48081/system/user/page?pageNo=1&pageSize=10
     * 为了统一管理，gateway配置前缀区分，
     * 通过这里将前缀拼上(网关调用)：http://172.16.135.39:48081/admin-api/system/user/page?pageNo=1&pageSize=10
     *
     * @param configurer 配置
     * @param api        API 配置
     */
    private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
        AntPathMatcher antPathMatcher = new AntPathMatcher(".");
        configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
                && antPathMatcher.match(api.getController(), clazz.getPackage().getName())); // 仅仅匹配 controller 包
    }

    @Bean
    @SuppressWarnings("InstantiationOfUtilityClass")
    public WebFrameworkUtils webFrameworkUtils(WebProperties webProperties) {
        // 由于 WebFrameworkUtils 需要使用到 webProperties 属性，所以注册为一个 Bean
        return new WebFrameworkUtils(webProperties);
    }
}
